home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / terminal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  10.5 KB  |  508 lines

  1. /*
  2.  * Start the terminal dialogue, fork the input routine, watch for the
  3.  * hot key so we can execute an option.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <curses.h>
  8. #include <signal.h>
  9. #include "config.h"
  10. #include "dial_dir.h"
  11. #include "misc.h"
  12. #include "modem.h"
  13. #include "param.h"
  14. #include "status.h"
  15. #include "xmodem.h"
  16.  
  17. #ifdef BSD
  18. #ifndef SIGCLD
  19. #define SIGCLD SIGCHLD
  20. #endif /* SIGCLD */
  21. #include <sys/file.h>
  22. #else /* BSD */
  23. #include <fcntl.h>
  24. #endif /* BSD */
  25.  
  26. #ifdef UNIXPC
  27. #include <sys/phone.h>
  28. #endif /* UNIXPC */
  29.  
  30. static int pid = -1;
  31.  
  32. terminal(extra_dir, input_status)
  33. char *extra_dir;
  34. int input_status;
  35. {
  36.     extern int fd;
  37.     int i, j, k, cr_lf, script;
  38.     char c, lf=10, *str_rep(), *keymac, *memset();
  39.     void help_screen(), line_set(), n_shell(), load_vs(), send_str();
  40.     void release_port(), do_input(), list_dir(), pexit(), zap_vs();
  41.     void st_line(), chg_dir(), screen_dump(), input_off(), suspend();
  42.     void info(), term_mode(), macro(), do_script();
  43.  
  44.                     /* if starting out in command mode */
  45.     if (!input_status) {
  46.         erase();
  47.         refresh();
  48.         st_line("");
  49.     }
  50.                     /* put stdin/stdout in terminal mode */
  51.     resetterm();
  52.     term_mode();
  53.     cr_lf = !strcmp(param->cr_out, "CR/LF");
  54.  
  55.     if (input_status) {
  56.         do_script(extra_dir);
  57.         do_input();
  58.     }
  59.  
  60.     while (1) {
  61.         read(0, &c, 1);
  62.         c &= 0x7f;
  63.                     /* is it the hot key? */
  64.         if (c == param->hot) {
  65.                     /* suspend input */
  66.             input_status = 0;
  67.             suspend(TRUE);
  68.             script = 0;
  69.  
  70.             /*
  71.              * Put the terminal in the curses mode, load the
  72.              * virtual screen and add the status line at the bottom.
  73.              */
  74.             fixterm();
  75.             load_vs();
  76.             st_line("");
  77. #ifndef OLDCURSES
  78.             keypad(stdscr, TRUE);
  79. #endif /* OLDCURSES */
  80.             i = wgetch(stdscr);
  81.                     /* map an additional hot key to -1 */
  82.             if (i == param->hot)
  83.                 i = -1;
  84.  
  85.             keymac = "";
  86.                     /* look for options */
  87.             k = -1;
  88.             switch (i) {
  89.                 case -1:    /* 2 "hots" means send 1 */
  90.                     k = param->hot;
  91.                     break;
  92.                 case '0':    /* help screen */
  93.                     help_screen(param->ascii_hot);
  94.                     break;
  95.                 case 'd':
  96.                 case 'D':    /* dialing directory */
  97.                     if (dial_menu())
  98.                         input_status = dial_win();
  99.                     script = input_status;
  100.                     break;
  101.                 case 'r':
  102.                 case 'R':    /* redial */
  103.                     if (redial())
  104.                         input_status = dial_win();
  105.                     script = input_status;
  106.                     break;
  107.                 case 'm':
  108.                 case 'M':    /* keyboard macros */
  109.                     macro();
  110.                     break;
  111.                 case 'p':
  112.                 case 'P':    /* line settings */
  113.                     if (ls_menu())
  114.                         line_set();
  115.                     break;
  116.                 case 'x':
  117.                 case 'X':    /* exit */
  118.                     pexit();
  119.                     break;
  120.                 case '4':    /* Unix gateway */
  121.                     n_shell();
  122.                     break;
  123.                 case 'i':
  124.                 case 'I':    /* program info screen */
  125.                     info(MANUAL_CLEAR);
  126.                     break;
  127.                 case 's':    /* setup menu */
  128.                 case 'S':
  129.                     input_status = setup_menu();
  130.                     break;
  131.                 case 'c':    /* clear the screen */
  132.                 case 'C':
  133.                     zap_vs();
  134.                     erase();
  135. #ifdef SHAREDMEM
  136.                     if (pid == -1) {
  137.                         for (j=0; j<LINES; j++)
  138.                             memset(status->vs[j], ' ', COLS);
  139.                     }
  140. #endif /* SHAREDMEM */
  141.                     break;
  142.                 case 'b':
  143.                 case 'B':    /* change directory */
  144.                     chg_dir();
  145.                     break;
  146.                 case 'e':
  147.                 case 'E':    /* toggle duplex */
  148.                     if (dir->duplex[dir->d_cur] == 'F')
  149.                         dir->duplex[dir->d_cur] = 'H';
  150.                     else
  151.                         dir->duplex[dir->d_cur] = 'F';
  152.  
  153.                         /* show changes */
  154.                     st_line("");
  155.                     k = wait_key(stdscr, 2);
  156.                     break;
  157.                 case 'h':
  158.                 case 'H':    /* hang up phone */
  159.                     release_port(VERBOSE);
  160.                     input_off();
  161.                     break;
  162.                 case 'l':
  163.                 case 'L':    /* toggle printer */
  164.                     status->print = status->print ? 0 : 1;
  165. #ifndef SHAREDMEM
  166.                     if (pid != -1)
  167.                         kill(pid, SIGUSR2);
  168. #endif /* SHAREDMEM */
  169.                         /* show changes */
  170.                     st_line("");
  171.                     k = wait_key(stdscr, 2);
  172.                     break;
  173.                 case '3':    /* toggle CR - CR/LF */
  174.                     if (!strcmp(param->cr_in, "CR")) {
  175.                         param->cr_in = str_rep(param->cr_in, "CR/LF");
  176.                         status->add_lf = 1;
  177.                     }
  178.                     else {
  179.                         param->cr_in = str_rep(param->cr_in, "CR");
  180.                         status->add_lf = 0;
  181.                     }
  182. #ifndef SHAREDMEM
  183.                     input_off();
  184.                     input_status++;
  185. #endif /* SHAREDMEM */
  186.                         /* show changes */
  187.                     st_line("");
  188.                     k = wait_key(stdscr, 2);
  189.                     break;
  190.                 case '7':    /* break key */
  191.                     if (fd != -1)
  192.                         tty_break(fd);
  193.  
  194.                     st_line("   break");
  195.                     break;
  196. #ifndef OLDCURSES
  197.                 case KEY_UP:
  198. #endif /* OLDCURSES */
  199.                 case 'u':
  200.                 case 'U':    /* send files */
  201.                     input_status = xfer_menu(UP_LOAD);
  202.                     break;
  203. #ifndef OLDCURSES
  204.                 case KEY_DOWN:
  205.                 case '\n':
  206. #endif /* OLDCURSES */
  207.                 case 'n':
  208.                 case 'N':    /* receive files */
  209.                     input_status = xfer_menu(DOWN_LOAD);
  210.                     break;
  211.                 case 't':
  212.                 case 'T':
  213.                     input_status = pass_thru();
  214.                     break;
  215.                 case 'f':
  216.                 case 'F':    /* list directory */
  217.                     list_dir();
  218.                     break;
  219.                 case 'g':    /* screen dump */
  220.                 case 'G':
  221.                     screen_dump();
  222.                     st_line(" screen dump");
  223.                     k = wait_key(stdscr, 2);
  224.                     break;
  225.                 case '1':    /* data logging */
  226.                     input_status = data_logging();
  227.                     break;
  228.                 case '2':    /* toggle log */
  229.                     if (!strcmp(status->log_path, "NOT_DEFINED")) {
  230.                         beep();
  231.                         st_line(" no log file");
  232.                         k = wait_key(stdscr, 2);
  233.                         break;
  234.                     }
  235.                     status->log = status->log ? 0 : 1;
  236. #ifndef SHAREDMEM
  237.                     if (pid != -1)
  238.                         kill(pid, SIGUSR1);
  239. #endif /* SHAREDMEM */
  240.                         /* show changes */
  241.                     st_line("");
  242.                     k = wait_key(stdscr, 2);
  243.                     break;
  244.                 /*
  245.                  * The following are the keyboard macros
  246.                  * corresponding to the shifted number keys.
  247.                  * (Too many keys... [control] [A] [shift] [1]
  248.                  * is hardly a shortcut!)
  249.                  */
  250.                 case '!':
  251.                     keymac = param->mac_1;
  252.                     break;
  253.                 case '@':
  254.                     keymac = param->mac_2;
  255.                     break;
  256.                 case '#':
  257.                     keymac = param->mac_3;
  258.                     break;
  259.                 case '$':
  260.                     keymac = param->mac_4;
  261.                     break;
  262.                 case '%':
  263.                     keymac = param->mac_5;
  264.                     break;
  265.                 case '^':
  266.                     keymac = param->mac_6;
  267.                     break;
  268.                 case '&':
  269.                     keymac = param->mac_7;
  270.                     break;
  271.                 case '*':
  272.                     keymac = param->mac_8;
  273.                     break;
  274.                 case '(':
  275.                     keymac = param->mac_9;
  276.                     break;
  277.                 case ')':
  278.                     keymac = param->mac_0;
  279.                     break;
  280.                 default:
  281.                     fputc(BEL, stderr);
  282.                     break;
  283.             }
  284.  
  285.             /*
  286.              * Repaint the stdscr (if we are already talking),
  287.              * get the stdin/stdout out of the curses mode and
  288.              * into the terminal mode.
  289.              */
  290.             if (fd != -1) {
  291.                 touchwin(stdscr);
  292.                 refresh();
  293.             }
  294.             resetterm();
  295.             term_mode();
  296.  
  297.             /*
  298.              * Some of the output processing options have to be
  299.              * faked...  Unfortunately, adding a LF to CR on
  300.              * output is one of them.
  301.              */
  302.             cr_lf = !strcmp(param->cr_out, "CR/LF");
  303.  
  304.                     /* run the auto-login script */
  305.             if (script)
  306.                 do_script(extra_dir);
  307.  
  308.                     /* re-start input routine */
  309.             if (input_status)
  310.                 do_input();
  311.             else
  312.                 suspend(FALSE);
  313.  
  314.                     /* send the macro */
  315.             if (*keymac != '\0')
  316.                 send_str(keymac, FAST);
  317.             /*
  318.              * If you pressed a key during one of the sleeping
  319.              * periods (typically the delay to see the status
  320.              * line change), let the keyboard value fall thru
  321.              * to the write() below.
  322.              */
  323.             if (k == -1)
  324.                 continue;
  325.             c = k;
  326.         }
  327.                     /* ignore errors if fd == -1 */
  328.         write(fd, &c, 1);
  329.                     /* map cr to cr_lf? */
  330.         if (c == '\r' && cr_lf) {
  331.             write(fd, &lf, 1);
  332.             /*
  333.              * Since you didn't type it... it doesn't get echoed
  334.              * by the driver.
  335.              */
  336.             if (dir->duplex[dir->d_cur] == 'H')
  337.                 write(1, &lf, 1);
  338.         }
  339.     }
  340. }
  341.  
  342. /*
  343.  * Fire up the input routine...
  344.  */
  345.  
  346. void
  347. do_input()
  348. {
  349.     extern int fd;
  350.     void error_win();
  351.     char first[(sizeof(int)*8)+1];
  352. #ifdef SHAREDMEM
  353.     extern int shm_id;
  354. #else /* SHAREDMEM */
  355.     char add_lf[2], log[2], print[2], dup_fd[3];
  356. #endif /* SHAREDMEM */
  357.                     /* if no TTY, or already on */
  358.     if (pid != -1 || fd == -1)
  359.         return;
  360.  
  361.     status->fd = fd;
  362.     status->add_lf = !strcmp(param->cr_in, "CR/LF");
  363.  
  364. #ifdef SHAREDMEM
  365.     sprintf(first, "%d", shm_id);
  366. #else /* SHAREDMEM */
  367.     sprintf(first, "%d", status->fd);
  368.     sprintf(dup_fd, "%d", status->dup_fd);
  369.     sprintf(add_lf, "%d", status->add_lf);
  370.     sprintf(log, "%d", status->log);
  371.     sprintf(print, "%d", status->print);
  372. #endif /* SHAREDMEM */
  373.  
  374.                     /* fork the input routine */
  375.     if (!(pid = fork())) {
  376. #ifdef BSD
  377.         setpgrp(0, getpid());
  378. #else /* BSD */
  379.         setpgrp();
  380. #endif /* BSD */
  381.  
  382. #ifdef SETUGID
  383.         setuid(getuid());
  384.         setgid(getgid());
  385. #endif /* SETUGID */
  386.  
  387. #ifdef SHAREDMEM
  388.         execlp("pcomm_input", "pcomm_input", first, (char *) 0);
  389. #else /* SHAREDMEM */
  390.         execlp("pcomm_input", "pcomm_input", first, dup_fd, add_lf,
  391.          log, print, status->log_path, status->vs_path, (char *) 0);
  392. #endif /* SHAREDMEM */
  393.         error_win(1, "Cannot find (or execute) the 'pcomm_input' program", "");
  394.     }
  395.  
  396.     return;
  397. }
  398.  
  399. /*
  400.  * shut it down...
  401.  */
  402.  
  403. void
  404. input_off()
  405. {
  406.     SIG_TYPE (*cstat)();
  407.  
  408.     if (pid != -1) {
  409.         /*
  410.          * This serves to periodically clean up the process table
  411.          */
  412.         cstat = signal(SIGCLD, SIG_IGN);
  413.         kill(pid, SIGTERM);
  414.         pid = -1;
  415.         signal(SIGCLD, cstat);
  416.     }
  417.     return;
  418. }
  419.  
  420. /*
  421.  * Hang up the phone but remain in the Pcomm command state.  Uses the
  422.  * hang_up string only, does *not* drop the DTR!
  423.  */
  424.  
  425. void
  426. hang_up(verbose)
  427. int verbose;
  428. {
  429.     extern int fd;
  430.     int junk;
  431.     void send_str(), st_line(), line_set();
  432.     char buf[80];
  433.     unsigned int sleep();
  434.                     /* sanity checking */
  435.     if (modem == NULL)
  436.         return;
  437.                     /* anything to hang up? */
  438.     if (modem->m_cur == -1 || fd == -1)
  439.         return;
  440.  
  441.     if (verbose)
  442.         st_line("disconnecting");
  443.                     /* special case for OBM */
  444.     if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  445. #ifdef UNIXPC
  446.         ioctl(fd, PIOCDISC);
  447.         /*
  448.          * The PIOCDISC ioctl screws up the file descriptor!!!
  449.          * No other phone(7) ioctl can fix it.  Whatever it does,
  450.          * it seems to escape detection with PIOCGETA and TCGETA.
  451.          * The best I can do is close the port and start over.
  452.          */
  453.         sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]);
  454.         close(fd);
  455.         fd = open(buf, O_RDWR|O_NDELAY);
  456.         line_set();
  457.         fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
  458. #endif /* UNIXPC */
  459.     }
  460.     else {
  461.         send_str(modem->hang_up[modem->m_cur], SLOW);
  462.  
  463.         /*
  464.          * Some modems do "damage" to the tty driver when they hang
  465.          * up by flashing the modem control lines on the port.  The
  466.          * following is some witchcraft designed to put the driver
  467.          * back the way it was.
  468.          */
  469.         sleep(1);
  470.         sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]);
  471.         junk = open(buf, O_RDWR);
  472.         close(junk);
  473.     }
  474.  
  475.     if (verbose)
  476.         st_line("");
  477.     return;
  478. }
  479.  
  480. /*
  481.  * Suspend or un-suspend the input routine.  The argument is used in
  482.  * non-shared memory configurations to give the vs_path file a fighting
  483.  * chance of being written to disk before load_vs() reads it.
  484.  */
  485.  
  486. /* ARGSUSED */
  487. void
  488. suspend(on)
  489. int on;
  490. {
  491.     void tty_restart();
  492.     unsigned int sleep();
  493.  
  494.     if (pid == -1)
  495.         return;
  496.     kill(pid, SIGINT);
  497.  
  498.     if (on) {
  499. #ifndef SHAREDMEM
  500.         sleep(1);
  501. #endif /* SHAREDMEM */
  502.     }
  503.     else                /* restart if XOFF received */
  504.         tty_restart();
  505.  
  506.     return;
  507. }
  508.